#include "bsp_gpio.h"

/* gpio初始化 */
void gpio_init(GPIO_Type *base, int pin, gpio_pin_config_t *config)
{
	if (config->direction == kGPIO_DigitalInput) /* 输入 */
	{
		base->GDIR &= ~(1 << pin);
	}
	else /* 输出 */
	{
		base->GDIR |= 1 << pin;
		gpio_pinwrite(base, pin, config->outputLogic); /* 设置默认输出电平 */
	}
	gpio_intconfig(base, pin, config->intteruptMode);
}

/* 读取指定IO */
int gpio_pinread(GPIO_Type *base, int pin)
{
	return (((base->DR) >> pin) & 0x1);
}

/* 设置指定IO */
void gpio_pinwrite(GPIO_Type *base, int pin, int value)
{
	if (value == 0U)
	{
		base->DR &= ~(1U << pin); /* 输出低电平 */
	}
	else
	{
		base->DR |= (1U << pin); /* 输出高电平 */
	}
}

/* 使能指定IO中断 */
void gpio_enableint(GPIO_Type *base, unsigned int pin)
{
	base->IMR |= (1 << pin);
}

/* 禁止指定IO中断 */
void gpio_disableint(GPIO_Type *base, unsigned int pin)
{
	base->IMR &= ~(1 << pin);
}

/* 清除中断标志位 */
void gpio_clearintflags(GPIO_Type *base, unsigned int pin)
{
	base->ISR |= (1 << pin);
}

/* gpio中断初始化函数 */
void gpio_intconfig(GPIO_Type *base, unsigned int pin, unsigned int pin_int_mode)
{
	volatile uint32_t *icr;
	uint32_t icrShift;
	icrShift = pin;
	base->EDGE_SEL &= ~(1 << pin);

	if (pin < 16)
	{
		icr = &(base->ICR1);
	}
	else
	{
		icr = &(base->ICR2);
		icrShift -= 16;
	}

	switch (pin_int_mode)
	{
	case KGPIO_IntLowLevel:
		*icr &= ~(3 << (2 * icrShift));
		break;
	case KGPIO_IntHighLevel:
		*icr &= ~(3 << (2 * icrShift));
		*icr |= (1 << (2 * icrShift));
		break;
	case KGPIO_IntRisingLevel:
		*icr &= ~(3 << (2 * icrShift));
		*icr |= (2 << (2 * icrShift));
		break;
	case KGPIO_IntFallingLevel:
		*icr &= ~(3 << (2 * icrShift));
		*icr |= (3 << (2 * icrShift));
		break;
	case KGPIO_IntRisingOrFallingLevel:
		base->EDGE_SEL |= (1 << pin);
		break;
	}
}
